﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SecurityAgent;
using System.ServiceModel;
using System.Web.Security;
using System.Security.Cryptography;

namespace SecurityAgent.Client.WinForm
{
    
    public class SASUserManager : SecurityAgent.Client.IUserManager
    {
        
        private MembershipProviderServiceReference.MembershipProviderServiceClient m_membershipClient;
        private MembershipProviderServiceReference.MembershipProviderServiceClient MembershipClient
        {
            get 
            {
                if( m_membershipClient == null ) m_membershipClient = new MembershipProviderServiceReference.MembershipProviderServiceClient();
                return m_membershipClient;
            }
        }

        private RoleProviderServiceReference.RoleProviderServiceClient m_roleClient;
        private RoleProviderServiceReference.RoleProviderServiceClient RoleClient
        {
            get
            {
                if (m_roleClient == null) m_roleClient = new RoleProviderServiceReference.RoleProviderServiceClient();
                return m_roleClient;
            }
        }

        private ProfileServiceReference.ProfileProviderServiceClient m_profileClient;
        private ProfileServiceReference.ProfileProviderServiceClient ProfileClient
        {
            get
            {
                if (m_profileClient == null) m_profileClient = new ProfileServiceReference.ProfileProviderServiceClient();
                return m_profileClient;
            }
        }

        private FieldSecurityServiceReference.FieldSecurityServiceClient m_fieldSecurityClient;
        private FieldSecurityServiceReference.FieldSecurityServiceClient FieldSecurityClient
        {
            get
            {
                if (m_fieldSecurityClient == null) m_fieldSecurityClient = new FieldSecurityServiceReference.FieldSecurityServiceClient();
                return m_fieldSecurityClient;
            }
        }

        private ObjectSecurityServiceReference.ObjectSecurityServiceClient m_objectSecurityClient;
        private ObjectSecurityServiceReference.ObjectSecurityServiceClient ObjectSecurityClient
        {
            get
            {
                if (m_objectSecurityClient == null) m_objectSecurityClient = new ObjectSecurityServiceReference.ObjectSecurityServiceClient();
                return m_objectSecurityClient;
            }
        }

        #region IUserManager Members
        //[SASExceptionHandler]
        public bool Authenticate(string applicationKey, string userName, string password, out string userToken)
        {
            try
            {
                //System.Text.UnicodeEncoding ue = new System.Text.UnicodeEncoding();
               

                //string newPass = string.Empty;

                //MembershipPasswordFormat passFormat = (MembershipPasswordFormat) MembershipClient.GetPasswordFormat(applicationKey);
                //switch( passFormat)
                //{
                //    case MembershipPasswordFormat.Clear:
                //        newPass = password;
                //        break;

                //    case MembershipPasswordFormat.Hashed:

                //         byte[] uePassword = ue.GetBytes(password);
                //byte[] RetVal = null;
                //        HMACSHA1 SHA1KeyedHasher = new HMACSHA1();
                //        SHA1KeyedHasher.Key = ue.GetBytes(applicationKey);
                //        RetVal = SHA1KeyedHasher.ComputeHash(uePassword);
                //        newPass = ue.GetString(RetVal);
                //        break;
                //    default:
                //        throw new Exception("Unsupport Password Format");

                //}

                userToken = MembershipClient.ValidateAndRegisterUser(applicationKey, userName, password);
                if (!String.IsNullOrEmpty(userToken))
                    return true;
                else
                    return false;
            }
            catch (FaultException<UnauthorizedAccessFault> e1)
            {
                throw new UnauthorizedAccessException(e1.Detail);
            }
            catch (FaultException<SecurityFault> e2)
            {
                throw new GeneralSecurityException(e2.Detail);
            }
            catch (FaultException e3)
            {
                throw new Exception(e3.Message + ":" + e3.Reason);
            }
        }

        //[SASExceptionHandler]
        public bool IsInRole(string applicationKey, string userToken, string userName, string role)
        {
            try
            {
                return RoleClient.IsUserInRole(applicationKey, userToken, userName, role);
            }
            catch (FaultException<UnauthorizedAccessFault> e1)
            {
                throw new UnauthorizedAccessException(e1.Detail);
            }
            catch (FaultException<SecurityFault> e2)
            {
                throw new GeneralSecurityException(e2.Detail);
            }
        }

        //[SASExceptionHandler]
        public string[] GetRoles(string applicationKey, string currentToken, string userName)
        {
            try{
            RoleProviderServiceReference.RoleCollection ret = RoleClient.GetRolesForUser(applicationKey, currentToken, userName);

            if (ret != null) return ret.ToArray();
            else
                return null;
            }
            catch (FaultException<UnauthorizedAccessFault> e1)
            {
                throw new UnauthorizedAccessException(e1.Detail);
            }
            catch (FaultException<SecurityFault> e2)
            {
                throw new GeneralSecurityException(e2.Detail);
            }
        }

        //[SASExceptionHandler]
        public AccessLevel CheckObjectAccess(string applicationKey, string currentToken, string objectName)
        {
            try{
            ObjectClaim oc = ObjectSecurityClient.GetObjectClaim(applicationKey, currentToken, objectName, false);

            if (oc != null) return oc.ObjectAccess;
            else
                return null;
            }
            catch (FaultException<UnauthorizedAccessFault> e1)
            {
                throw new UnauthorizedAccessException(e1.Detail);
            }
            catch (FaultException<SecurityFault> e2)
            {
                throw new GeneralSecurityException(e2.Detail);
            }
        }

        //[SASExceptionHandler]
        public ObjectClaim[] GetClaims(string applicationKey, string currentToken, string category)
        {
            try{
            if (String.IsNullOrEmpty(category))
            {
                return ObjectSecurityClient.GetAllObjects(applicationKey, currentToken, true);
            }
            else
            {
                return ObjectSecurityClient.GetObjectsByCategory(applicationKey, currentToken, category, true);
            }
            }
            catch (FaultException<UnauthorizedAccessFault> e1)
            {
                throw new UnauthorizedAccessException(e1.Detail);
            }
            catch (FaultException<SecurityFault> e2)
            {
                throw new GeneralSecurityException(e2.Detail);
            }
        }

        public ObjectClaim[] GetClaims(string applicationKey, string currentToken)
        {
            try
            {
                return GetClaims(applicationKey, currentToken, string.Empty);
            }
            catch (FaultException<UnauthorizedAccessFault> e1)
            {
                throw new UnauthorizedAccessException(e1.Detail);
            }
            catch (FaultException<SecurityFault> e2)
            {
                throw new GeneralSecurityException(e2.Detail);
            }
        }

        #endregion

        #region IUserManager Members

        //[SASExceptionHandler]
        public ProfilePropertyValueCollection GetPropertyValues(string applicationKey, string userToken, string UserName, string[] PropertyNames)
        {
            try
            {
                ProfileServiceReference.ProfilePropertyValueCollection result = ProfileClient.GetPropertyValues(applicationKey, userToken, UserName, PropertyNames);

                ProfilePropertyValueCollection ret = new ProfilePropertyValueCollection();
                foreach (ProfilePropertyValue p in result)
                    ret.Add(p);
                return ret;
            }
            catch (FaultException<UnauthorizedAccessFault> e1)
            {
                throw new UnauthorizedAccessException(e1.Detail);
            }
            catch (FaultException<SecurityFault> e2)
            {
                throw new GeneralSecurityException(e2.Detail);
            }
        }

        //[SASExceptionHandler]
        public bool SetPropertyValues(string applicationKey, string userToken, string userName, ProfilePropertyValue[] values)
        {
            try
            {
                return ProfileClient.SetPropertyValues(applicationKey, userToken, userName, values);
            }
            catch (FaultException<UnauthorizedAccessFault> e1)
            {
                throw new UnauthorizedAccessException(e1.Detail);
            }
            catch (FaultException<SecurityFault> e2)
            {
                throw new GeneralSecurityException(e2.Detail);
            }
        }

        #endregion
    }
}
